package com.dhz.common.redis;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import redis.clients.jedis.JedisPool;

import java.io.IOException;
import java.util.List;

/**
 * Redis 链接池初始化
 */
public class RedisConnectionFactory implements InitializingBean {
    private static final Logger logger = LoggerFactory.getLogger(RedisConnectionFactory.class);

    private List<RedisServerConf> serverList;

    /***
     * 根据权重获取JedisPool,权重值weight在配置中设置
     * @return pool instance
     */
    public RedisServerConf server() {
        RedisServerConf bestServer = null;

        int weightTotal = 0;

        for (RedisServerConf server : serverList) {
            if (server.isDown()) {
                continue;
            }

            server.setCurrentWeight(server.getCurrentWeight() + server.getEffectiveWeight());
            weightTotal += server.getEffectiveWeight();
            if (server.getEffectiveWeight() < server.getWeight()) {
                server.setEffectiveWeight(server.getEffectiveWeight() + 1);
            }

            if (bestServer == null || server.getCurrentWeight() > bestServer.getCurrentWeight()) {
                bestServer = server;
            }
        }

        if (bestServer == null) {
            return null;
        }
        bestServer.setCurrentWeight(bestServer.getCurrentWeight() - weightTotal);

        return bestServer;
    }

    public List<RedisServerConf> getServerList() {
        return serverList;
    }

    public void setServerList(List<RedisServerConf> serverList) {
        this.serverList = serverList;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(serverList, "Redis Connection Config is required!");

        // TODO 根据consList创建连接池
        for (RedisServerConf conf : serverList) {
            // 初始化Jedis连接池
            conf.setPool(createRedisPool(conf));
            // 设置权重参数
            conf.setEffectiveWeight(conf.getWeight());
            conf.setCurrentWeight(0);
            conf.setDown(conf.getWeight()<0);

            // 如果配置传入的lua 文件路径，需在载入对应的redis实例中
            try {
                conf.loadLuaScript();
            } catch (IOException e) {
                logger.error("Can't load Redis Id Generator Lua Script File with : {}", conf.getLuaFilePath());
                throw new RuntimeException("Can't load Redis Id Generator Lua Script File!");
            }
        }

    }

    public JedisPool createRedisPool(RedisServerConf conf) {
        if (conf.getPoolConfig() == null) {
            return new JedisPool(new GenericObjectPoolConfig(), conf.getHost(), conf.getPort(), conf.getTimeout(), conf.getPassword(), conf.getDatabase());
        }
        return new JedisPool(conf.getPoolConfig(), conf.getHost(), conf.getPort(), conf.getTimeout(), conf.getPassword(), conf.getDatabase());
    }

}
